﻿using Panuon.UI.Silver;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Configuration;
using System.Security.Cryptography.X509Certificates;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Windows;
using Newtonsoft.Json;
using static psy_service.fwpt.fwpt;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace psy_service
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : WindowX
    {
        public static bool FwptThread = true;

        public MainWindow()
        {
            HttpWebRequestElement httpWebRequestElement = new HttpWebRequestElement();
            httpWebRequestElement.UseUnsafeHeaderParsing = true;
            InitializeComponent();
            Title = Title + " v." + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
            InitNotifyIcon();
            fwpt_start();
            string[] starts = Environment.GetCommandLineArgs();
            if (starts.Count() > 1)
            {
                if (starts[1] == "ssssss")
                {
                    Visibility = Visibility.Hidden;
                }
            }
        }

        public static HttpListener listener;
        static string url = "https://127.0.0.1:28000";
        static string[] uris =
        {
                    url+"/api/verifyPin",
                    url+"/api/readCertInfo",
                    url+"/api/clientHello",
                    url+"/api/clientAuth",
                    url+"/api/getVersion",
                    url+"/client/getsh",
                    url+"/",
                    url+"/index.html"
        };

        private void ListenerCallback(IAsyncResult result)
        {
            string json = string.Empty, Path = string.Empty;

            try
            {
                HttpListenerContext context = listener.EndGetContext(result);
                //context = listener.EndGetContext(result);
                HttpListenerRequest request = context.Request;
                HttpListenerResponse response = context.Response;
                response.ContentType = "application/json; charset=UTF-8";
                response.Headers["Connection"] = "keep-alive";
                response.Headers["Access-Control-Allow-Origin"] = "*";
                response.Headers["Access-Control-Methods"] = "POST";
                //response.Headers["Remote Address"] = "127.0.0.1:28000";
                //设置授权，尝试解决Jquery跨域问题
                response.Headers["Access-Control-Allow-Origin"] = "*";
                response.Headers["Access-Control-Allow-Methods"] = "GET,POST";
                response.Headers["Access-Control-Max-Age"] = "1000";

                string uri = string.Format("https://{0}:{1}{2}", request.Url.Host, request.Url.Port, request.Url.AbsolutePath);
                Path = request.Url.AbsolutePath.ToString();
                string PathQuery = request.Url.PathAndQuery;

                if (uris.Contains(uri))
                {
                    if (Path == "/" || Path == "/index.html")
                    {
                        PathQuery = "测试请求";
                    }

                    if (Path == "/client/getsh")
                    {
                        PathQuery = "连接请求";
                    }

                    Runlogout("接收请求：" + PathQuery);
                    switch (Path)
                    {
                        case "/":
                        case "/index.html":
                            context.Response.StatusCode = 200;
                            context.Response.StatusDescription = "OK";
                            response.ContentType = "";
                            json = Properties.Resources.GoodHTML;
                            break;
                        case "/client/getsh":
                            context.Response.StatusCode = 200;
                            context.Response.StatusDescription = "OK";
                            json = getNsrsbh(request, response);
                            break;
                        case "/api/verifyPin":
                            context.Response.StatusCode = 200;
                            context.Response.StatusDescription = "OK";
                            json = verifyPin(request, response);
                            break;
                        case "/api/readCertInfo":
                            context.Response.StatusCode = 200;
                            context.Response.StatusDescription = "OK";
                            json = readCertInfo(request, response);
                            break;
                        case "/api/clientHello":
                            context.Response.StatusCode = 200;
                            context.Response.StatusDescription = "OK";
                            json = clientHello(request, response);
                            break;
                        case "/api/clientAuth":
                            context.Response.StatusCode = 200;
                            context.Response.StatusDescription = "OK";
                            json = clientAuth(request, response);
                            break;
                        case "/api/getVersion":
                            context.Response.StatusCode = 200;
                            context.Response.StatusDescription = "OK";
                            json = getVersion(request);
                            break;
                    }

                    byte[] buffer = Encoding.UTF8.GetBytes(json);

                    //加密输出字符串
                    if (Path == "/api/clientHello")
                    {
                        try
                        {
                            JObject jo = JObject.Parse(json);
                            string[] values = jo.Properties().Select(item => item.Value.ToString()).ToArray();
                            string clientHello = values[2].ToString();
                            string Desstring = Encrypt.SHA512Encrypt(clientHello);
                            json = json.Replace(clientHello, Desstring);
                        }
                        catch
                        {
                            Runlogout("clientHello获取失败");
                            json = "{\"code\":999002,\"msg\":\"票税云综合服务： clientHello失败\"}";
                        }
                    }

                    if (Path == "/api/clientAuth")
                    {
                        try
                        {
                            JObject jo = JObject.Parse(json);
                            string[] values = jo.Properties().Select(item => item.Value.ToString()).ToArray();
                            string clientAuth = values[2].ToString();
                            string Desstring = Encrypt.SHA512Encrypt(clientAuth);
                            json = json.Replace(clientAuth, Desstring);
                        }
                        catch
                        {
                            Runlogout("clientAuth获取失败");
                            json = "{\"code\":999003,\"msg\":\"票税云综合服务： clientAuth失败\"}";
                        }
                    }
                    response.ContentLength64 = buffer.Length;
                    Stream output = response.OutputStream;
                    new Thread(() =>
                    {
                        output.Write(buffer, 0, buffer.Length);
                    }).Start();
                    if (Path == "/api/getVersion")
                    {
                        if (nsrsbh == string.Empty && sessionId == string.Empty && psyurl == string.Empty)
                        {
                            ServiceController[] services = ServiceController.GetServices();
                            foreach (ServiceController service in services)
                            {
                                if (service.ServiceName == "CHINATAX_CRYPT")
                                {
                                    FwptThread = false;
                                    listener.Abort();
                                    if (service.Status != ServiceControllerStatus.Running)
                                    {
                                        Runlogout("启动增值税发票综合服务平台官方应用……");
                                        service.Start();
                                        service.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 30));
                                        if (service.Status == ServiceControllerStatus.Running)
                                        {
                                            Runlogout("增值税发票综合服务平台官方应用已启动");
                                        }
                                    }

                                    new Thread(() =>
                                    {
                                        Thread.Sleep(1000 * 60);
                                        Dispatcher.Invoke(new Action(() =>
                                        {
                                            FwptThread = true;
                                            fwpt_start();
                                        }));
                                    }).Start();
                                }
                            }
                        }
                    }

                }
                else
                {
                    context.Response.StatusCode = 404;
                    context.Response.StatusDescription = "NOT FOUND";
                }

                if (Path != "/" && Path != "/index.html")
                {
                    Runlogout(json);
                }

                context.Response.Close();
            }
            catch (ObjectDisposedException)
            { }
            catch (HttpListenerException)
            { }
            catch (Exception ex)
            {
                Runlogout("发生错误：" + ex);
            }
        }

        #region 托盘事件
        //定义一个变量
        private System.Windows.Forms.NotifyIcon notifyIcon;
        private void InitNotifyIcon()
        {
            notifyIcon = new System.Windows.Forms.NotifyIcon();
            notifyIcon.BalloonTipText = "票税云-发票综合服务已启动";
            notifyIcon.ShowBalloonTip(2000);
            notifyIcon.Text = "票税云-发票综合服务";
            notifyIcon.Icon = System.Drawing.Icon.ExtractAssociatedIcon(System.Windows.Forms.Application.ExecutablePath);
            notifyIcon.Visible = true;

            //打开菜单项
            System.Windows.Forms.MenuItem open = new System.Windows.Forms.MenuItem("显示界面");
            open.Click += new EventHandler(Show);

            //退出菜单项
            System.Windows.Forms.MenuItem exit = new System.Windows.Forms.MenuItem("退出");
            exit.Click += new EventHandler(Close);

            //关联托盘控件
            System.Windows.Forms.MenuItem[] childen = new System.Windows.Forms.MenuItem[] { open, exit };
            notifyIcon.ContextMenu = new System.Windows.Forms.ContextMenu(childen);
            notifyIcon.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler((o, e) =>
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Left) Show(o, e);
            });
        }

        private void Show(object sender, EventArgs e)
        {
            Visibility = Visibility.Visible;
            ShowInTaskbar = true;
            Activate();
        }

        private void Close(object sender, EventArgs e)
        {
            Application.Current.Shutdown();
        }

        private void WindowX_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            ShowInTaskbar = false;
            //indowState = WindowState.Minimized;
            Visibility = Visibility.Hidden;
            e.Cancel = true;
        }
        #endregion

        private void WindowX_ContentRendered(object sender, EventArgs e)
        {

        }

        private void fwpt_start()
        {
            try
            {
                //停止官方应用
                stopCHINATAX_CRYPT();

                //结束28000端口进程
                killport28000();

                //初始化
                X509Certificate2 certificate = new X509Certificate2(Properties.Resources.localhost, "12345678", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
                X509Store store = new X509Store(StoreLocation.LocalMachine);
                store.Open(OpenFlags.ReadWrite);
                store.Add(certificate);
                store.Close();

                ProcessStartInfo psi = new ProcessStartInfo
                {
                    FileName = "netsh",
                    Arguments = "http add sslcert ipport=127.0.0.1:28000 certhash=" + certificate.Thumbprint + " appid={5c66f06d-dd10-43d7-ac65-512d58911e68}"
                };

                if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major < 6)
                {
                    psi = new ProcessStartInfo
                    {
                        FileName = "httpcfg",
                        Arguments = "set ssl -i 127.0.0.1:28000 -h " + certificate.Thumbprint
                    };
                }
                psi.CreateNoWindow = true;
                psi.UseShellExecute = false;
                psi.RedirectStandardOutput = true;
                Process proc = Process.Start(psi);
                proc.WaitForExit();

                listener = new HttpListener();
                //listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                foreach (string s in uris.Select(u => u.Substring(0, u.LastIndexOf("/") + 1)).Distinct())
                {
                    listener.Prefixes.Add(s);
                }

                listener.Start();
                if (listener.IsListening)
                {
                    Runlogout("票税云发票平台登陆服务已启动，测试链接：https://127.0.0.1:28000");
                }
                new Thread(() =>
                {
                    while (FwptThread)
                    {
                        var result = listener.BeginGetContext(ListenerCallback, listener);
                        result.AsyncWaitHandle.WaitOne();
                    }
                })
                { IsBackground = true }.Start();

            }
            catch (Exception ex)
            {
                Runlogout("客户端启动失败：\r\n" + ex);
            }
        }

        private void Runlogout(string text)
        {
            Dispatcher.Invoke(new Action(() =>
            {
                //fwpt_runLogs.Text += text + "\r\n";
                fwpt_runLogs.AppendText(string.Format("{0:yyyy-MM-dd HH:MM:ss}：{1}\r\n", DateTime.Now, text));
                fwpt_runLogs.ScrollToEnd();
            }));
        }

        private void stopCHINATAX_CRYPT()
        {
            ServiceController[] services = ServiceController.GetServices();
            foreach (ServiceController service in services)
            {
                if (service.ServiceName == "CHINATAX_CRYPT")
                {
                    if (service.Status == ServiceControllerStatus.Running || service.Status == ServiceControllerStatus.StartPending)
                    {
                        Runlogout("停止综服平台官方应用……");
                        service.Stop();
                        service.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 30));
                    }
                }
            }
        }

        public void startCHINATAX_CRYPT()
        {
            ServiceController[] services = ServiceController.GetServices();
            bool Servicebool = false;
            foreach (ServiceController service in services)
            {
                if (service.ServiceName == "CHINATAX_CRYPT")
                {
                    Servicebool = true;
                    if (service.Status != ServiceControllerStatus.Running)
                    {
                        Runlogout("启动增值税发票综合服务平台官方应用……");
                        service.Start();
                        service.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 30));
                        if (service.Status == ServiceControllerStatus.Running)
                        {
                            Runlogout("增值税发票综合服务平台官方应用已启动");
                        }
                    }
                }
            }
            if (!Servicebool)
            {
                Runlogout("没有安装增值税发票综合服务平台官方应用");
            }
        }

        private void swzs_app_Click(object sender, RoutedEventArgs e)
        {
            if ((bool)swzs_app.IsChecked)
            {
                FwptThread = false;
                listener.Abort();
                Runlogout("票税云发票平台登陆服务已停止");
                startCHINATAX_CRYPT();
            }
            else
            {
                //stopCHINATAX_CRYPT();
                FwptThread = true;
                fwpt_start();
            }
        }

        private void killport28000()
        {
            Process p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.CreateNoWindow = true;
            List<int> list_pid = GetPidByPort(p, 28000);

            if (list_pid.Count > 0)
            {
                Runlogout("发现占用28000端口进程，尝试结束");
                p.Start();
                foreach (var item in list_pid)
                {
                    p.StandardInput.WriteLine("taskkill /pid " + item + " /f");
                    p.StandardInput.WriteLine("exit");
                }
                p.Close();
                killport28000();
            }
        }

        private static List<int> GetPidByPort(Process p, int port)
        {
            int result;
            bool b = true;
            p.Start();
            p.StandardInput.WriteLine(string.Format("netstat -ano|find \"{0}\"", port));
            p.StandardInput.WriteLine("exit");
            StreamReader reader = p.StandardOutput;
            string strLine = reader.ReadLine();
            List<int> list_pid = new List<int>();
            while (!reader.EndOfStream)
            {
                strLine = strLine.Trim();
                if (strLine.Length > 0 && ((strLine.Contains("TCP") || strLine.Contains("UDP"))))
                {
                    Regex r = new Regex(@"\s+");
                    string[] strArr = r.Split(strLine);
                    if (strArr.Length >= 4)
                    {
                        b = int.TryParse(strArr[3], out result);
                        if (b && !list_pid.Contains(result))
                            list_pid.Add(result);
                    }
                }
                strLine = reader.ReadLine();
            }
            p.WaitForExit();
            reader.Close();
            p.Close();
            return list_pid;
        }
    }
}
